package com.akk.module.hkpay.util;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * 接口测试
 */
public class InterfaceTest {
	
	private static final String URL = "http://113.108.195.242:9999/hicardwallet/api/center.do";
	private static final String PASSWORD = "ef775988943825d2871e1cfa75473ec0";
	private static final String INST_NO = "99999999";
	
	public static void main(String[] args) {
		boolean flag = sendHicardWalletPay();
		System.out.println(flag);
	}

	/**
	 * 请求汇卡钱包
	 */
	private static boolean sendHicardWalletPay() {
		// 请求头
		LinkedHashMap<String, String> reqHeader = new LinkedHashMap<String, String>();
		reqHeader.put("version", "100"); // 版本号
		reqHeader.put("security", "none"); // 安全模式
		reqHeader.put("transType", "7000"); // 接口类型
		reqHeader.put("dtClient", "2017-11-03 18:10:00"); // 客户端时间戳
		reqHeader.put("channelType", "1"); // 渠道类型
		// 请求内容
		LinkedHashMap<String, String> reqBody = new LinkedHashMap<String, String>();
		String orderNo = UUID.randomUUID().toString();
		reqBody.put("tradeSequence", orderNo + System.currentTimeMillis()); // 交易序号
		reqBody.put("orderNo", orderNo); // 交易订单号
		reqBody.put("type", "B"); // 交易类型-差错入账
		reqBody.put("profitOrderNo", ""); // 分润来源订单号
		reqBody.put("cardNo", "123456789012345678"); // 交易卡号
		reqBody.put("payAccountType", "1"); // 入账账户类型
		reqBody.put("receiveMerchNo", INST_NO); // 入账商户号/机构号
		reqBody.put("terminalNo", "12345678"); // 终端号
		reqBody.put("merchNo", "123456789012345"); // 交易商户
		reqBody.put("instNo", INST_NO); // 交易机构号
		reqBody.put("amount", String.valueOf(100)); // 金额，分为单位
		reqBody.put("fee", String.valueOf(1)); // 手续费，分为单位
		reqBody.put("transDate", "2017-11-03"); // 交易日期
		reqBody.put("transTime", "18:40:00"); // 交易时间
		reqBody.put("extraData", "测试"); // 附加域
		reqBody.put("remark", "差错入账"); // 备注
		reqBody.put("signature", sign(reqBody, PASSWORD, "key")); // 签名
		// 完整请求
		LinkedHashMap<String, Object> request = new LinkedHashMap<String, Object>();
		request.put("header", reqHeader);
		request.put("body", reqBody);

		// 转json
		String requestJson = toJson(request);
		System.out.println(requestJson);
		
		
		String responseJson = "";
		try {
			
			// 客户端
			CloseableHttpClient client = HttpClients.createDefault();
			try {
				HttpPost hp = new HttpPost(URL);
				hp.setEntity(new StringEntity(requestJson, Charset.forName("UTF-8")));
				HttpResponse response = client.execute(hp);
				int statusCode = response.getStatusLine().getStatusCode();
				HttpEntity entity = response.getEntity();
				byte[] respContent = EntityUtils.toByteArray(entity);
				EntityUtils.consume(entity);
				if (statusCode != 200) {
					return false;
				}
				responseJson = new String(respContent, Charset.forName("UTF-8"));
			} finally {
				client.close();
			}
			
			System.out.println(responseJson);

			// 解析汇卡钱包返回
			@SuppressWarnings("unchecked")
			LinkedHashMap<String, LinkedHashMap<String, String>> hkqbMap = parse(responseJson,
					LinkedHashMap.class);
			LinkedHashMap<String, String> hkqbBody = hkqbMap.get("body");
			if (hkqbBody == null) {
				return false;
			}
			if ("0000".equals(hkqbBody.get("code"))) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	

	/**
	 * 对参数key进行排序(java.util.Arrays的排序方法)，然后使用指定密钥进行md5加签，忽略null值及空符串
	 * @param params
	 * @param secretKey
	 * @return
	 */
	public static String sign(Map<String, String> params, String secretKey, String signKeyName) {
		// 对参数排序
		LinkedHashMap<String, String> sorts = new LinkedHashMap<String, String>();
		Set<String> keySet = params.keySet();
		String[] keys = new String[keySet.size()];
		keys = keySet.toArray(keys);
		Arrays.sort(keys);
		for (int i = 0; i < keys.length; i++) {
			String key = keys[i];
			sorts.put(key, params.get(key));
		}
		// 加签
		StringBuilder signKeys = new StringBuilder();
		for (Entry<String, String> entry : sorts.entrySet()) {
			if(entry.getValue()==null || entry.getValue().isEmpty()) {
				continue;
			}
			signKeys.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
		}
		signKeys.append(signKeyName).append("=").append(secretKey);
		return md5UTF8Hex(signKeys.toString());
	}
	
	/** 通常用的MD5加密：MD5加密字符串的UTF-8字节 */
	public static String md5UTF8Hex(String str) {
		try {
			byte[] bs = str.getBytes("UTF-8");
			MessageDigest md = MessageDigest.getInstance("MD5");	
			return byteToHex(md.digest(bs));
		} catch(UnsupportedEncodingException e){
			throw new RuntimeException(e); // 中文平台，都会支持GBK字符集
		} catch (NoSuchAlgorithmException  e) {
			throw new RuntimeException(e);	// 因为JDK实现了MD5算法，所以该异常理论上不可能出现
		}
	}

	/** 将byte[]转为16进制的字符串数组 */
	public static String byteToHex(byte[] bs){
		StringBuilder sb = new StringBuilder();			
		for (int i = 0; i < bs.length; i++) {
			int c = bs[i];
			if(c<0){
				c += 256;
			}
			// 转16进制字符串
			String hex = Integer.toHexString(c);
			if(hex.length()==1){
				sb.append("0");
			}
			sb.append(hex);
		}
		return sb.toString();
	}

	/** 将一个java对象换为json字符串 */
	public static String toJson(Object object){
		return new Gson().toJson(object);
	}
	
	/** 将一个json字符串转换为java对象 */
	public static <T> T parse(String json, Class<T> classs){
		return new Gson().fromJson(json,classs);
	}

}
